﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Net.NetworkInformation;
using System.Net.Sockets;
using System.Runtime.Serialization.Formatters.Binary;

namespace ThePresenter.Net.NetCom
{
	static class NetComTools
	{
		public static BinaryFormatter BinaryFormatter = new BinaryFormatter();

		/// <summary>
		/// Array of local IPAddresses
		/// </summary>
		public static IPAddress[] LocalIPAddresses
		{
			get {
				if (NetComTools._LocalIPAddressesCache == null)
					NetComTools.ForceUpdateLocalIPAddresses();

				return NetComTools._LocalIPAddressesCache;
			}
		}
		private static IPAddress[] _LocalIPAddressesCache = null;

		/// <summary>
		/// Updates local IPAdresses list
		/// </summary>
		public static void ForceUpdateLocalIPAddresses()
		{
			NetworkInterface[] NICs;
			List<IPAddress> LocalIPs;

			try
			{
				NICs = NetworkInterface.GetAllNetworkInterfaces();
				LocalIPs = new List<IPAddress>();

				if (NICs == null || NICs.Length < 1)
					return;

				UnicastIPAddressInformationCollection UniCastAdresses;

				DebugClass.DebugWrite("Tools", "Found {0} interfaces.", NICs.Length);
				
				foreach (NetworkInterface NIC in NICs)
				{
					if (NIC.OperationalStatus != OperationalStatus.Up)
						continue;

					if (NIC.NetworkInterfaceType == NetworkInterfaceType.Loopback)
						continue;

					if (NIC.NetworkInterfaceType == NetworkInterfaceType.Tunnel)
						continue;

					DebugClass.DebugWrite("Tools", "Interface {0} is valid", NIC.Name);
					UniCastAdresses = NIC.GetIPProperties().UnicastAddresses;

					if (UniCastAdresses != null)
					{
						DebugClass.DebugWrite("Tools", "and have following IPs:");
						foreach (UnicastIPAddressInformation IFAddressInfo in UniCastAdresses)
						{
							if (IFAddressInfo.Address.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)
							{
								LocalIPs.Add(IFAddressInfo.Address);
								DebugClass.DebugWrite("Tools", "{0}", IFAddressInfo.Address.ToString());
							}
						}
					}
					else
					{
						DebugClass.DebugWrite("Tools", "but have not valid IP.");
					}
				}

				if (LocalIPs.Count > 0)
					NetComTools._LocalIPAddressesCache = LocalIPs.ToArray();
				else
					throw new NoSuitableInterfacesException();
			}
			catch (NetworkInformationException NIE)
			{
				DebugClass.ShowMessage("Unable to get network interfaces : " + NIE.Message);
			}
			catch (NoSuitableInterfacesException NSIE)
			{
				DebugClass.ShowMessage("No valid network interface : " + NSIE.Message);
			}
		}

		public static bool IsLocalIPAddress(IPAddress IP)
		{
			foreach (IPAddress ip in NetComTools.LocalIPAddresses)
			{
				if (ip.Equals(IP)) return true;
			}

			return false;
		}

		public static IPEndPoint[] GetLocalEndPoints(int Port)
		{
			List<IPEndPoint> epList = new List<IPEndPoint>();

			foreach (IPAddress IP in NetComTools.LocalIPAddresses)
				epList.Add(new IPEndPoint(IP, Port));

			return epList.ToArray();
		}
	}
}
